﻿package src.states {
	import src.game.PointsHolder;
	import src.game.LifeHolder;
	import src.game.SoundButton;
	import src.game.managers.ObjectFactory;
	import src.game.Letter;
	import src.game.managers.ObjectMover;
	import src.game.managers.ObjectProperties;
	import src.Const;
	import src.game.managers.ObjectRemover;
	import src.utils.Keys;
	import src.game.Crock;
	import flash.events.Event;
	import flash.display.DisplayObjectContainer;
	import flash.events.KeyboardEvent;
	import flash.geom.Rectangle;
	import flash.display.MovieClip;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	import flash.utils.getDefinitionByName;
	import src.sound.SoundPlayer;
	import flash.media.Sound;
	import src.game.managers.SoundManager;
	import flash.events.MouseEvent;
	
	
	public class Gameplay extends GameState {
		private var points:PointsHolder;
		private var lives:LifeHolder;
		
		private var objectFactory:ObjectFactory;
		private var objectMover:ObjectMover;
		private var objectRemover:ObjectRemover;
		
		private var gameArea:Rectangle;
		private var creationArea:Rectangle;
		
		private var wave:MovieClip;
		private var crock:Crock;
		
		private var timer:Timer;
		private var play:Boolean;
		
		private var levelNumber:int;		
		public function Gameplay(display:DisplayObjectContainer, gameStates:GameStatesMachine) {
			super(display, gameStates);
			crock = new Crock();
			initWave();
			initPoints();
			initLives();
			initAreas();
			initManagers();
		}
		
		public override function restart():void {
			points.restartPoints();
			lives.restartLives();
			levelNumber = 0;
			objectMover.removeAll();
			objectFactory.removeAll();
			play = false;
		}
		
		public override function init():void {
			super.init();
			play = true;
			displayContent.stage.stageFocusRect = false;
			displayContent.stage.focus = displayContent;
			initKeys();
			initCrock();			points.show();
			lives.show();
			//initSoundButton();
			objectFactory.nextLevel(initKeysToPressed());
			objectFactory.setObjectsSpeed(Const.OBJECTS_SPEED[levelNumber]);
			objectFactory.setObjectsRotationSpeed(Const.OBJECTS_ROTATION_SPEED[levelNumber]);
			objectFactory.addEventListener(Event.ADDED, addNewObject);
			objectFactory.startPlacingObjects();
			levelNumber++;
		}
		
		private function initPoints():void {
			points = new PointsHolder(displayContent);
			points.setSize(displayContent.width, displayContent.height / 4);
			points.setPosition(0, displayContent.height - points.getHeight() / 2 );
			points.init();
			points.hide();
		}
		
		private function initLives():void {
			lives = new LifeHolder(displayContent);
			lives.setSize(displayContent.width / 20, displayContent.height);
			lives.setPosition(displayContent.width - lives.getWidth(), 50);
			lives.init(Const.LIVES);
			lives.hide();
		}
		
		private function initWave():void {
			wave = new Wave();
			displayContent.addChild(wave);
			wave.y = displayContent.stage.stageHeight - wave.height;
		}
		
		private function initAreas():void {
			var letter:Letter = new Letter(87);
			creationArea = new Rectangle(letter.width / 2, 0, displayContent.stage.stageWidth - letter.width, 0);
			gameArea = new Rectangle(0, 0, displayContent.stage.stageWidth, displayContent.stage.stageHeight - crock.height / 2 + letter.height / 3);
		}
		
		private function initManagers():void {
			initObjectFactory();
			objectMover = new ObjectMover(displayContent);
			objectRemover = new ObjectRemover();
			objectRemover.setGameArea(gameArea);
		}
		
		private function initObjectFactory():void {
			objectFactory = new ObjectFactory(Const.TIMER_DELAY);
			var objectProperties:ObjectProperties = new ObjectProperties(creationArea);
			objectFactory.setObjectProperties(objectProperties);
		}
		
		private function initKeys():void {
			addKeysListeners(displayContent.stage);
		}
		
		private function initCrock():void {
			crock = new Crock();
			crock.y = displayContent.height + crock.height / 2;
			crock.x = gameArea.width / 2;
			crock.setFoodSpeed(Const.OBJECTS_SPEED[levelNumber]);
			displayContent.addChild(crock);
			displayContent.setChildIndex(crock, displayContent.getChildIndex(wave));
		}
		
		private function initKeysToPressed():Vector.<int> {
			var v:Vector.<int> = new Vector.<int>();
			for (var i:int = Const.LETTERS_MIN_RANGE; i<=Const.LETTERS_MAX_RANGE; i++) 
				v.push(i);
			for (i = Const.DIGITS_MIN_RANGE; i<=Const.DIGITS_MAX_RANGE; i++) 
				v.push(i);
			return v;
		}
		
		public override function update():void {
			if (play) {
				objectMover.update();
				updateCrock();
				checkObjectsInTheArea();
				checkGameConditios();
			}
		}
		
		private function updateCrock():void {
			if (objectMover.getObjectsNumber() > 0)
				crock.updateFoodPosition(objectMover.getObjectAt(0).x, objectMover.getObjectAt(0).y);
			else
				crock.updateFoodPosition(crock.x, -displayContent.stage.stageHeight);
			crock.update();
		}
		
		public function addNewObject(event:Event):void {
			for (var i:int = objectFactory.numberOfObjectsToDisplay() - 1; i>= 0; i--) {
				objectMover.add(objectFactory.getObjectAt(i));
				displayContent.setChildIndex(objectMover.getObjectAt(objectMover.getObjectsNumber() - 1), displayContent.getChildIndex(crock));
				trace (objectFactory.getObjectAt(i).getText());
			}
			
			var SoundClass:Class = getDefinitionByName("s_" + objectFactory.getObjectAt(0).getText()) as Class;
			SoundManager.getInstance().add(new SoundPlayer( new SoundClass()));
			objectFactory.clearAllObjectsToDisplay();
			objectFactory.stopPlacingObjects();
		}
		
		private function checkGameConditios() {
			if (checkForEndGame() ) {
				if (timer == null) {
					objectFactory.stopPlacingObjects();
					timer = new Timer(3000, 1);
					timer.addEventListener(TimerEvent.TIMER, levelLost);
					timer.start();
				}
			}
			else if (checkForNextLevel() )
				gameStates.setCurrentState(gameStates.getEndLevelState());
		}
		
		private function checkForEndGame():Boolean {
			return ( lives.areLivesLeft() ) ? false : true;
		}
		
		private function checkForNextLevel():Boolean {
			return ( objectFactory.numberOfObjectsToBeCreated() == 0 &&
					objectFactory.numberOfObjectsToDisplay() == 0 &&
					objectMover.getObjectsNumber() == 0 &&
					lives.areLivesLeft() ) ? true : false;
		}

		private function checkObjectsInTheArea():void {
			for (var i:int = objectMover.getObjectsNumber() - 1; i >= 0; i--)
				if ( !objectRemover.isInArea(objectMover.getObjectAt(i))) {
					objectMover.removeAt(i);
					lives.lifeLost();
					objectFactory.startPlacingObjects();
					playSound(new SoundPlayer(new CrockEating()));
				}
		}
		
		private function levelLost(event:TimerEvent):void {
			gameStates.setCurrentState(gameStates.getEndGameState());
		}
		
		private function addKeysListeners(keysStateListener:DisplayObjectContainer):void {
			//keysStateListener.addEventListener(FocusEvent.FOCUS_OUT, disableAllKeys, false, 0, true);
			//keysStateListener.addEventListener(KeyboardEvent.KEY_DOWN, keyDown, false, 0, true);
			keysStateListener.addEventListener(KeyboardEvent.KEY_UP, keyUp, false, 0, true);
		}
		
		private function removeKeysListeners(keysStateListener:DisplayObjectContainer):void {
			//keysStateListener.removeEventListener(FocusEvent.FOCUS_OUT, disableAllKeys);
			//keysStateListener.removeEventListener(KeyboardEvent.KEY_DOWN, keyDown);
			keysStateListener.removeEventListener(KeyboardEvent.KEY_UP, keyUp);
		}
		
		private function keyUp(event:KeyboardEvent):void {
			var wasRemoved:Boolean = false;
			objectRemover.pressedKey(event.keyCode);
			for (var i:int = objectMover.getObjectsNumber() - 1; i >= 0; i--)
				if (objectRemover.checkToRemove(objectMover.getObjectAt(i))) {
					wasRemoved = true;
					objectMover.removeWithAnimation(i);
					objectFactory.startPlacingObjects();
				}
			if (!wasRemoved) {
				lives.lifeLost();
				playSound(new SoundPlayer(new LetterRemoved()));
			}
			else {
				points.addPoints();
				playSound(new SoundPlayer(new Cheer()));
			}
			trace("key down: key code" + event.keyCode + " char code " + event.charCode);
		}
		
		private function playSound(s:SoundPlayer) {
			var sm:SoundManager = SoundManager.getInstance();
			sm.add(s);
		}
		
		public override function dispose():void {
			super.dispose();
			play = false;
			removeKeysListeners(displayContent.stage);
			objectFactory.stopPlacingObjects();
			objectFactory.removeEventListener(Event.ADDED, addNewObject);
			objectMover.removeAll();
			displayContent.removeChild(crock);
			//timer.stop();
			timer = null;
		}

	}
	
}
